package cn.tannn.surenessdemo.user.service.impl;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.jdevelops.entity.basics.util.UUIDUtils;
import cn.jdevelops.entity.basics.vo.SerializableVO;
import cn.jdevelops.exception.annotation.DisposeException;
import cn.jdevelops.exception.exception.BusinessException;
import cn.tannn.surenessdemo.user.dao.AuthRoleResourceBindDao;
import cn.tannn.surenessdemo.user.dao.AuthRouteDao;
import cn.tannn.surenessdemo.user.dao.AuthRouteResourceBindDao;
import cn.tannn.surenessdemo.user.entity.AuthRoute;
import cn.tannn.surenessdemo.user.service.AuthRouteService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.SQLIntegrityConstraintViolationException;
import java.util.List;
import java.util.Optional;

/**
 * 前端路由
 *
 * @author tnnn
 * @version V1.0
 * @date 2022-07-28 09:07
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class AuthRouteServiceImpl implements AuthRouteService {

    private final AuthRouteDao authRouteDao;
    private final AuthRouteResourceBindDao authRouteResourceBindDao;
    private final AuthRoleResourceBindDao authRoleResourceBindDao;


    @Override
    @DisposeException(messages = "当前路由以存在,请勿重复添加",
            exceptions = SQLIntegrityConstraintViolationException.class)
    public boolean addAuthRoute(AuthRoute authRoute) {
        if(StringUtils.isBlank(authRoute.getCode())){
            authRoute.setCode(UUIDUtils.getInstance().generateShortUuid());
        }
        authRouteDao.save(authRoute);
        return true;
    }

    @Override
    public boolean updateAuthRoute(AuthRoute authRoute) {
        try {
            AuthRoute byCode = authRouteDao.findByCode(authRoute.getCode());
            Assert.notNull(byCode,() -> new BusinessException("路由不存在"));
            byCode.copy(authRoute);
            authRouteDao.saveAndFlush(byCode);
            return true;
        }catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteAuthRoute(List<String> routeCodes) {
        if(!routeCodes.isEmpty()){
            authRouteDao.deleteByCodeIn(routeCodes);
            authRouteResourceBindDao.deleteByRouteCodeIn(routeCodes);
        }else {
            return false;
        }
        return true;
    }

    @Override
    public List<AuthRoute> getAuthRoutes() {
        return authRouteDao.findAll(Sort.by(Sort.Direction.ASC,
                SerializableVO.of(AuthRoute::getSortNumber)));
    }

    @Override
    public Optional<List<AuthRoute>> getAuthRoutesOp() {
        List<AuthRoute> authRoutes = authRouteDao.findAll(Sort.by(Sort.Direction.ASC,
                SerializableVO.of(AuthRoute::getSortNumber)));
        return Optional.of(authRoutes);
    }


    @Override
    public List<AuthRoute> getRouteOwnRole(String roleCode) {
        // 资源
        List<String> resources = authRoleResourceBindDao.findRoleBindResourceList2Str(roleCode);
        return authRouteResourceBindDao.findRouteBindResourceList(resources);
    }

    @Override
    public List<AuthRoute> getRouteByResource(String resourceCode) {
        return authRouteResourceBindDao.findRouteBindResourceList(resourceCode);
    }

    @Override
    public List<AuthRoute> userRoute(String userCode) {
        return authRouteDao.findByUser(userCode);
    }

    @Override
    public  List<Tree<String>> userRouteTrue(String userCode) {
        List<AuthRoute> byUser = authRouteDao.findByUser(userCode);
        //转换器
        return routeTrue(byUser);
    }

    @Override
    public List<Tree<String>> routeTrue(List<AuthRoute> authRoute) {
        //配置
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        // 自定义属性名 都要默认值的
        treeNodeConfig.setWeightKey("sortNumber");
        // 最大递归深度
        treeNodeConfig.setDeep(10);
        //转换器
        return TreeUtil.build(authRoute, "0", treeNodeConfig,
                (treeNode, tree) -> {
                    tree.setId(treeNode.getCode());
                    tree.setParentId(treeNode.getParentCode());
                    tree.setWeight(treeNode.getSortNumber());
                    tree.setName(treeNode.getName());
                    // 扩展属性 ...
                    tree.putExtra("routeType", treeNode.getRouteType());
                    tree.putExtra("route", treeNode.getRoute());
                    tree.putExtra("icon", treeNode.getIcon());
                    tree.putExtra("state", treeNode.getStatus());
                    tree.putExtra("component", treeNode.getComponent());
                    tree.putExtra("componentName", treeNode.getComponentName());
                });
    }

}
